package org.example.concurrentUtils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.*;

/**
 * CountDownLatch 测试类
 *
 * @author ZhengDp
 * @Date 2023/2/20 21:40
 */
@Slf4j(topic = "c.CountDownLatchTest")
public class CountDownLatchTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        test6();
    }

    private static void test6() throws InterruptedException, ExecutionException {
        RestTemplate restTemplate = new RestTemplate();
        CountDownLatch latch = new CountDownLatch(4);
        log.info("begin");
        ExecutorService service = Executors.newCachedThreadPool();
        Future<Map<String, Object>> f1 = service.submit(() -> {
            return restTemplate.getForObject("http://127.0.0.1:9905/order/{1}", Map.class, 1);
        });
        Future<Map<String, Object>> f2 = service.submit(() -> {
            return restTemplate.getForObject("http://127.0.0.1:9905/product/{1}", Map.class, 1);
        });
        Future<Map<String, Object>> f3 = service.submit(() -> {
            return restTemplate.getForObject("http://127.0.0.1:9905/product/{1}", Map.class, 2);
        });
        Future<Map<String, Object>> f4 = service.submit(() -> {
            return restTemplate.getForObject("http://127.0.0.1:9905/logistics/{1}", Map.class, 1);
        });
        log.info("{}",f1.get());
        log.info("{}",f2.get());
        log.info("{}",f3.get());
        log.info("{}",f4.get());
        log.info("end ...");
        service.shutdown();
    }

    private static void test5() throws InterruptedException {
        RestTemplate restTemplate = new RestTemplate();
        CountDownLatch latch = new CountDownLatch(4);
        log.info("begin");
        ExecutorService service = Executors.newCachedThreadPool();
        service.submit(() -> {
            Map<String, Object> response = restTemplate.getForObject("http://127.0.0.1:9905/order/{1}", Map.class, 1);
            log.info("end order : {}", response);
            latch.countDown();
        });
        service.submit(() -> {
            Map<String, Object> response1 = restTemplate.getForObject("http://127.0.0.1:9905/product/{1}", Map.class, 1);
            log.info("end product : {} ", response1);
            latch.countDown();
        });
        service.submit(() -> {
            Map<String, Object> response2 = restTemplate.getForObject("http://127.0.0.1:9905/product/{1}", Map.class, 2);
            log.info("end product : {} ", response2);
            latch.countDown();
        });
        service.submit(() -> {
            Map<String, Object> response3 = restTemplate.getForObject("http://127.0.0.1:9905/logistics/{1}", Map.class, 1);
            log.info("end logistics : {}", response3);
            latch.countDown();
        });
        latch.await();
        log.info("end ...");
        service.shutdown();
    }

    private static void test4() {
        RestTemplate restTemplate = new RestTemplate();
        log.info("begin");
        Map<String, Object> response = restTemplate.getForObject("http://127.0.0.1:9905/order/{1}", Map.class, 1);
        log.info("end order : {}", response);
        Map<String, Object> response1 = restTemplate.getForObject("http://127.0.0.1:9905/product/{1}", Map.class, 1);
        Map<String, Object> response2 = restTemplate.getForObject("http://127.0.0.1:9905/product/{1}", Map.class, 2);
        log.info("end product : {} , {} ", response1, response2);
        Map<String, Object> response3 = restTemplate.getForObject("http://127.0.0.1:9905/logistics/{1}", Map.class, 1);
        log.info("end logistics : {}", response3);
    }

    private static void test3() throws InterruptedException {
        ExecutorService service = Executors.newFixedThreadPool(10);
        CountDownLatch latch = new CountDownLatch(10);
        Random random = new Random(System.currentTimeMillis());
        String[] all = new String[10];
        for (int j = 0; j < 10; j++) {
            final int k = j;
            service.submit(() -> {
                for (int i = 0; i <= 100; i++) {
                    try {
                        Thread.sleep(random.nextInt(100));
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    all[k] = i + "%";
                    // "\r" : 光标前置
                    System.out.print("\r" + Arrays.toString(all));
                }
                latch.countDown();
            });
        }
        latch.await();
        System.out.println("\nGame Begin ... ");
        service.shutdown();
    }

    private static void test2() {
        CountDownLatch countDownLatch = new CountDownLatch(3);
        ExecutorService service = Executors.newFixedThreadPool(4);
        service.submit(() -> {
            try {
                log.info("begin ...");
                Thread.sleep(1000);
                countDownLatch.countDown();
                log.info("end ...");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        service.submit(() -> {
            try {
                log.info("begin ...");
                Thread.sleep(1500);
                countDownLatch.countDown();
                log.info("end ...");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        service.submit(() -> {
            try {
                log.info("begin ...");
                Thread.sleep(2000);
                countDownLatch.countDown();
                log.info("end ...");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        service.submit(() -> {
            try {
                log.info("waiting ... ");
                countDownLatch.await();
                log.info("wait end ...");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
    }

    private static void test() throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(3);
        long start = System.currentTimeMillis();
        new Thread(() -> {
            try {
                log.info("begin ...");
                Thread.sleep(1000);
                countDownLatch.countDown();
                log.info("end ...");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }).start();

        new Thread(() -> {
            try {
                log.info("begin ...");
                Thread.sleep(2000);
                countDownLatch.countDown();
                log.info("end ...");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }).start();

        new Thread(() -> {
            try {
                log.info("begin ...");
                Thread.sleep(1500);
                countDownLatch.countDown();
                log.info("end ...");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }).start();

        // 主线程等待其他线程执行完毕
        log.info("waiting ... ");
        countDownLatch.await();
        log.info("wait end ...");
    }
}
